﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using System.Xml.XPath;
using System.Xml.Xsl;
using Newtonsoft.Json;

namespace XmlRuleBuilder
{
    public static class JSONValidator
    {
        public static void Validate(XmlNode node, string mdXml, Macro macro)
        {
            // Input files
            string ruleJson = "Schema.json";
            string instanceJson = "Sample.json";

            bool isXSLTTransformSuccess = true;
            StreamWriter myWriter = new StreamWriter(ruleJson);

            // Transform the XSL stylesheet
            if (node.Attributes["processor"].Value == "xslt+jsonschema")
            {
                try
                {
                    // Load the Metadata file
                    XPathDocument myXPathDoc = new XPathDocument(mdXml);

                    // Repalce the macros                       
                    string temp = Helper.MacroReplacement(node.InnerXml, macro);

                    // Load the XSL from the node
                    XslCompiledTransform myXslTrans = new XslCompiledTransform(true);
                    XmlReader reader = XmlReader.Create(new StringReader(temp));
                    reader.ReadToDescendant("xsl:stylesheet");
                    myXslTrans.Load(reader);

                    // Write to Schema.rng
                    myXslTrans.Transform(myXPathDoc, null, myWriter);
                    myWriter.Close();
                }
                catch (Exception ex)
                {
                    isXSLTTransformSuccess = false;
                    Console.WriteLine("XSLT Transform failed. Exception: {0}", ex.Message);
                }
            }
            else
            {                
                myWriter.Write(Helper.MacroReplacement(node["jsonschema"].InnerText, macro));
                myWriter.Close();
            }

            if (isXSLTTransformSuccess)
            {
                StreamReader ruleStreamReader = new StreamReader(ruleJson);
                StreamReader instanceStreamReader = new StreamReader(instanceJson);
                JsonSchema schema = null;
                bool isSchemaValid = true;
                bool isInstanceValid = true;

                try
                {
                    schema = JsonSchema.Parse(ruleStreamReader.ReadToEnd().ToString());
                }
                catch (Exception ex)
                {
                    isSchemaValid = false;
                    Console.WriteLine(string.Format("Malformed JSON Schema : {0}", ex.Message));
                }

                StringReader stringReader = null;
                if (isSchemaValid)
                {
                    try
                    {
                        JObject instance = JObject.Parse(instanceStreamReader.ReadToEnd().ToString());
                        stringReader = new StringReader(instance.ToString());
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(string.Format("Malformed JSON instance : {0}", ex.Message));
                    }
                }

                bool isValid = true;
                if (isInstanceValid)
                {
                    try
                    {
                        using (JsonTextReader jsonTextReader = new JsonTextReader(stringReader))
                        {
                            using (JsonValidatingReader jsonValidatingReader = new JsonValidatingReader(jsonTextReader))
                            {
                                jsonValidatingReader.Schema = schema;

                                try
                                {
                                    while (jsonValidatingReader.Read())
                                    {
                                    };
                                }
                                catch (JsonSchemaException ex)
                                {
                                    Console.WriteLine("JSON instance is invalid!");
                                    Console.WriteLine(string.Format("Line Number = {0}, ErrorDetails = {1}", ex.LineNumber, ex.Message));
                                    isValid = false;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("JSON instance is invalid!");
                        Console.WriteLine(string.Format("ErrorDetails = {0}", ex.Message));
                        isValid = false;
                    }
                }

                if (isValid)
                {
                    Console.WriteLine("JSON instance is valid!");
                }
            }
        }
    }
}
